package com.cloud.note.service.impl;

import com.cloud.note.service.FileStorageService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.Objects;
import java.util.UUID;
import java.util.stream.Stream;

@Service
public class FileStorageServiceImpl implements FileStorageService {

    @Value("${file.upload-dir}")
    private String uploadDir;

    private Path fileStorageLocation;

    @PostConstruct
    public void init() {
        this.fileStorageLocation = Paths.get(uploadDir).toAbsolutePath().normalize();
        try {
            Files.createDirectories(this.fileStorageLocation);
        } catch (IOException ex) {
            throw new RuntimeException("Could not create the directory where the uploaded files will be stored.", ex);
        }
    }

    @Override
    public String storeFile(MultipartFile file, String userId, String noteId) throws IOException {
        // 检查文件名
        String originalFileName = StringUtils.cleanPath(Objects.requireNonNull(file.getOriginalFilename()));
        if (originalFileName.contains("..")) {
            throw new RuntimeException("文件名包含无效的路径序列 " + originalFileName);
        }

        // 创建用户和笔记目录
        Path userDir = this.fileStorageLocation.resolve(userId);
        Path noteDir = userDir.resolve(noteId);
        Files.createDirectories(noteDir);

        // 生成新的文件名，防止文件覆盖
        String newFileName = UUID.randomUUID().toString() + "_" + originalFileName;
        Path targetLocation = noteDir.resolve(newFileName);

        // 保存文件
        Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);

        // 返回相对路径
        return userId + "/" + noteId + "/" + newFileName;
    }

    @Override
    public Path getFilePath(String fileName) {
        return this.fileStorageLocation.resolve(fileName);
    }

    @Override
    public Stream<Path> loadAll() throws IOException {
        return Files.walk(this.fileStorageLocation, 1)
                .filter(path -> !path.equals(this.fileStorageLocation))
                .map(this.fileStorageLocation::relativize);
    }

    @Override
    public void deleteFile(String fileName) throws IOException {
        Path filePath = this.fileStorageLocation.resolve(fileName);
        Files.deleteIfExists(filePath);

        // 尝试删除空目录
        Path parentDir = filePath.getParent();
        if (parentDir != null && !parentDir.equals(this.fileStorageLocation)) {
            try (Stream<Path> dirContents = Files.list(parentDir)) {
                if (dirContents.count() == 0) {
                    Files.deleteIfExists(parentDir);

                    // 再尝试删除上级空目录
                    Path grandParentDir = parentDir.getParent();
                    if (grandParentDir != null && !grandParentDir.equals(this.fileStorageLocation)) {
                        try (Stream<Path> gpDirContents = Files.list(grandParentDir)) {
                            if (gpDirContents.count() == 0) {
                                Files.deleteIfExists(grandParentDir);
                            }
                        }
                    }
                }
            }
        }
    }
}